package guhong.play.commandsystem.gui;

import cn.hutool.core.lang.Singleton;
import com.sun.java.swing.plaf.motif.MotifScrollPaneUI;
import guhong.play.commandsystem.CommandManager;
import guhong.play.commandsystem.gui.key.KeyListenerHandler;
import guhong.play.commandsystem.gui.key.KeyListenerHandlerManager;
import guhong.play.commandsystem.gui.key.type.KeyType;
import guhong.play.commandsystem.gui.ui.UIManger;
import guhong.play.commandsystem.util.ToolUtil;
import guhong.play.commandsystem.util.print.PrintUtil;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.List;

/**
 * 主窗口
 *
 * @author : 李双凯
 * @date : 2019-11-20 22:32
 **/
public class MainWindow extends JFrame {

    private static final CoreKeyListener CORE_KEY_LISTENER = new CoreKeyListener();

    private static final Font DEFAULT_FONT = new Font("宋体", Font.PLAIN, 20);

    public MainWindow() throws HeadlessException {
        // 设置主窗体
        addWindowListener(new MainWindowListener());
        setTitle("Java命令系统");
        setWindowSize();
        setVisible(true);
        setLocationRelativeTo(null);

        // 设置终端文本域
        JTextArea terminal = new JTextArea();
        terminal.addKeyListener(CORE_KEY_LISTENER);
        terminal.setFont(DEFAULT_FONT);
        terminal.setLineWrap(true);
        terminal.setEditable(false);
        add(terminal, BorderLayout.CENTER);

        // 设置滚动窗口
        JScrollPane terminalScroll = new JScrollPane(terminal);
        terminalScroll.setSize(this.getSize());
        terminalScroll.setUI(new MotifScrollPaneUI());
        terminalScroll.setVerticalScrollBarPolicy(
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        add(terminalScroll);

        // 创建底部区域
        JPanel bottomPanel = new JPanel(new BorderLayout());
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);

        // 左边部分使用JTextArea作为文本框
        JTextArea leftTextArea = new JTextArea();
        leftTextArea.setEditable(false); // 设置为不可输入
        leftTextArea.setFont(DEFAULT_FONT);
        splitPane.setLeftComponent(leftTextArea);


        // 右边部分使用JTextField作为输入框
        JTextField commandInputBox = new JTextField();
        commandInputBox.addKeyListener(CORE_KEY_LISTENER);
        commandInputBox.setFont(DEFAULT_FONT);
        splitPane.setRightComponent(commandInputBox);

        // 将JSplitPane添加到底部区域
        bottomPanel.add(splitPane, BorderLayout.CENTER);
        bottomPanel.setPreferredSize(new Dimension(this.getWidth(), (int) (this.getHeight() * 0.08)));
        add(bottomPanel, BorderLayout.SOUTH);

        // 注册组件
        UIManger uiManger = CommandManager.getUiManger();
        uiManger.put(UIManger.UI_NAME_MAIN, this);
        uiManger.put(UIManger.UI_NAME_TERMINAL, terminal);
        uiManger.put(UIManger.UI_NAME_TERMINAL_SCROLL, terminalScroll);
        uiManger.put(UIManger.UI_NAME_COMMAND_INPUT_BOX, commandInputBox);

        // 加载系统
        initSystem();
        // 重新设置宽度，响应滚动条
        this.setSize(this.getWidth() + 1, this.getHeight());
    }


    private void setWindowSize() {
        // 得到显示器屏幕的宽、高
        int systemWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
        int systemHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
        // 得到窗体的宽、高
        int windowsWidth = this.getWidth();
        int windowsHeight = this.getHeight();
        // 130是为了更好的显示list命令
        int finishWidth = (systemWidth - windowsWidth) / 2 + 130;
        int finishHeight = (systemHeight - windowsHeight) / 2 + 130;
        setSize(finishWidth, finishHeight);
    }

    /**
     * 初始化命令系统
     */
    private void initSystem() {
        // 初始化
        PrintUtil.println("欢迎使用Java命令系统");
        PrintUtil.println("正在加载命令（第一次执行可能需要点时间）...");
        CommandManager.init();
        PrintUtil.println("加载完成：版本：v"+ ToolUtil.getProjectVersion());

        // 打印说明信息
        PrintUtil.println("\n帮助：");
        PrintUtil.println("1、可以通过 [list] 命令查看当前系统的所有命令。");
        PrintUtil.println("2、可以通过 [help 命令] 命令查看指定命令的帮助信息。如：[help list]。");
        PrintUtil.println("\n————————————————————————————————————————————————\n\n");
        PrintUtil.println(ToolUtil.getHeadInfo());
    }


}

class CoreKeyListener implements KeyListener {

    private static KeyListenerHandlerManager keyListenerHandlerManager = Singleton.get(KeyListenerHandlerManager.class);

    /**
     * 当前输入的键盘标识，因为keyTyped中拿不到code
     */
    private volatile int currentKeyCode = 0;

    /**
     * 键盘输入一个值的时候
     *
     * @param e 事件对象
     */
    @Override
    public synchronized void keyTyped(KeyEvent e) {
        e.setKeyCode(currentKeyCode);

        // 让输入框获得焦点
        // 这会影响到一些快捷键的使用，比如Ctrl + C
//        CommandManager.getUiManger().getFocusInWindow();

        // 监听打印字符的按键。比如：A B C D
        java.util.List<KeyListenerHandler> keyListenerHandlerList = keyListenerHandlerManager.get(KeyType.PRINT);
        for (KeyListenerHandler keyListenerHandler : keyListenerHandlerList) {
            if (keyListenerHandler.isListener(e)) {
                keyListenerHandler.execute();
                return;
            }
        }
    }

    /**
     * 键盘按下的时候，只是按下，还没有在终端中输入值
     *
     * @param e 事件对象
     */
    @Override
    public synchronized void keyPressed(KeyEvent e) {
        currentKeyCode = e.getKeyCode();

        // 让输入框获得焦点
        // 这会影响到一些快捷键的使用，比如Ctrl + C
//        CommandManager.getUiManger().getFocusInWindow();

        // 监听不打印字符的按键。比如: 方向键 ↑ ↓ ← →
        List<KeyListenerHandler> keyListenerHandlerList = keyListenerHandlerManager.get(KeyType.NOT_PRINT);
        for (KeyListenerHandler keyListenerHandler : keyListenerHandlerList) {
            if (keyListenerHandler.isListener(e)) {
                keyListenerHandler.execute();
                return;
            }
        }
    }

    /**
     * 键盘弹回去的时候，只要按键弹回去，不管有没有输入值，都会触发
     * 比如中文输入时，输入后并不会直接触发keyPressed方法，因为中文输入是需要确认的，所以系统判定此时还没有按下去
     * 但是键盘肯定会被释放（弹回来），所以这种情况就会先进这个方法。
     * @param e 事件对象
     */
    @Override
    public synchronized void keyReleased(KeyEvent e) {
        currentKeyCode = e.getKeyCode();
    }

}

/**
 * 主窗口的监听
 */
class MainWindowListener implements WindowListener {


    @Override
    public void windowOpened(WindowEvent e) {
    }


    @Override
    public void windowClosing(WindowEvent e) {
        CommandManager.shutdown();
    }


    @Override
    public void windowClosed(WindowEvent e) {
    }


    @Override
    public void windowIconified(WindowEvent e) {

    }


    @Override
    public void windowDeiconified(WindowEvent e) {

    }


    @Override
    public void windowActivated(WindowEvent e) {

    }


    @Override
    public void windowDeactivated(WindowEvent e) {

    }


}

